#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>


#include <vector>

#define OPEN_MAX_GUESS (256)

void limit_close( int min = 2 )
{
	int open_max;

	if( (open_max = sysconf( _SC_OPEN_MAX )) < 0 ) {
		open_max = OPEN_MAX_GUESS;
	}
	// printf( "open_max %d\n", open_max );

	for( int i =  (min < 0 ? -1 : min ) + 1; i <= open_max; i++ ) {
		close( i );
	}
}

void opened_close( int min = 2 )
{
	DIR *dp = opendir( "/proc/self/fd" );

	if( NULL == dp ) {
		fprintf( stderr, "opendir error, errno %d", errno );
	}

	struct dirent dir;
	struct dirent *p_dir = NULL;
	const int dir_fd = dirfd( dp );
	std::vector< int > fds;
	while( readdir_r( dp, &dir, &p_dir ) == 0 && p_dir != NULL ) {
		if( *(dir.d_name) == '.' )
			continue;
		int fd = atoi( dir.d_name );
		if( dir_fd != fd && fd > min ) {
			fds.push_back( fd );
		}
	}

	for( size_t i = 0; i < fds.size(); i++ ) {
		printf( "fd %d\n", fds.at( i ) );
		close( fds.at( i ) );
	}

	closedir( dp );
}

void print_now( void )
{
	struct timeval tv;

	gettimeofday( &tv, NULL );
	printf( "NOW %lu.%lu\n", tv.tv_sec, tv.tv_usec );
}

void open_fd( int num )
{
	for( int i = 0; i < num; i++ )
		open( "/dev/null", O_RDONLY );
	return;
}

int main( int argc, char *argv[] )
{
	int times = 10000;
	int fd_num = 200;

	if( argc > 1 )
		times = atoi( argv[1] );
	if( argc > 2 )
		fd_num = atoi( argv[2] );
	print_now();
	for( int i = 0; i < times; i++ ) {
		open_fd( fd_num );
		limit_close();
	}
	print_now();
	for( int i = 0; i < times; i++ ) {
		open_fd( fd_num );
		opened_close();
	}
	print_now();

	return 0;
}
